package cn.yunyichina.utils.commons;

import cn.yunyichina.utils.constants.Encoding;
import okhttp3.*;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import javax.net.ssl.*;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.Map;

/**
 * Created by Lullaby on 2016/9/30.
 */
public class HttpUtil {

    /**
     * 发送GET请求
     *
     * @param url
     * @return
     * @throws IOException
     */
    public static String get(String url) throws IOException {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(url).build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    }

    /**
     * 发送POST请求(缺省使用text/html媒体类型)
     *
     * @param content
     * @param url
     * @return
     * @throws IOException
     */
    public static String post(String content, String url) throws IOException {
        OkHttpClient client = new OkHttpClient();
        RequestBody body = RequestBody.create(MediaType.parse(HttpContentType.TEXTHTML.getType()), content);
        Request request = new Request.Builder().url(url).post(body).build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    }

    /**
     * Http Basic Authorization Post
     *
     * @param password
     * @param content
     * @param url
     * @return
     * @throws IOException
     */
    public static String httpBasicPost(String username, String password, String content, String url, HttpContentType contentType) throws IOException {
        String secret = "Basic " + Base64.encodeBase64String(new String(username + ":" + password).getBytes("UTF-8"));

        OkHttpClient client = new OkHttpClient();
        RequestBody body = RequestBody.create(MediaType.parse(contentType.getType()), content);
        Request request = new Request.Builder().url(url).addHeader("Authorization", secret).post(body).build();

        Response response = client.newCall(request).execute();
        return response.body().string();
    }

    /**
     * Http Basic Authorization Post
     *
     * @param key
     * @param value
     * @param url
     * @param contentType
     * @return
     * @throws IOException
     */
    public static String httpBasicPostWithKeyValue(String key, String value, String content, String url, HttpContentType contentType) throws IOException {
        String secret = key + " " + value;

        OkHttpClient client = new OkHttpClient();
        RequestBody body = RequestBody.create(MediaType.parse(contentType.getType()), content);
        Request request = new Request.Builder().url(url).addHeader("Authorization", secret).post(body).build();

        Response response = client.newCall(request).execute();
        return response.body().string();
    }

    /**
     * 发送POST请求(自定义媒体类型)
     *
     * @param content
     * @param url
     * @return
     * @throws IOException
     */
    public static String post(String content, String url, HttpContentType contentType) throws IOException {
        OkHttpClient client = new OkHttpClient();
        RequestBody body = RequestBody.create(MediaType.parse(contentType.getType()), content);
        Request request = new Request.Builder().url(url).post(body).build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    }

    /**
     * 微信退费HTTP请求
     *
     * @param url      微信退费接口地址
     * @param content  发送数据
     * @param password 证书密码
     * @param certPath 证书CLASSPATH绝对路径
     * @return
     * @throws Exception
     */
    public static String doWechatSslPost(String url, String content, String password, String certPath) throws Exception {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");

        try (BufferedInputStream instream = new BufferedInputStream(HttpUtil.class.getResourceAsStream(certPath), 127)) {
            keyStore.load(instream, password.toCharArray());
        }

        SSLContext sslContext = SSLContext.getInstance("TLS");

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

        X509TrustManager trustManager = null;
        for (TrustManager manager : trustManagers) {
            if (manager instanceof X509TrustManager) {
                trustManager = (X509TrustManager) manager;
                break;
            }
        }

        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, password.toCharArray());
        KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();

        sslContext.init(keyManagers, null, new SecureRandom());

        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

        OkHttpClient client = new OkHttpClient.Builder().sslSocketFactory(sslSocketFactory, trustManager).build();

        RequestBody body = RequestBody.create(MediaType.parse(HttpContentType.TEXTHTML.getType()), content);
        Request request = new Request.Builder().url(url).post(body).build();

        try (Response response = client.newCall(request).execute()) {
            return response.body().string();
        }
    }

    /**
     * 构建application/x-www-form-urlencoded表单提交的参数
     *
     * @param params
     * @return
     */
    public static String buildFormUrlEncodedParams(Map<String, String> params) throws UnsupportedEncodingException {
        StringBuffer buffer = new StringBuffer();

        for (Map.Entry<String, String> entry : params.entrySet()) {
            String key = entry.getKey(), value = entry.getValue();
            if (StringUtils.isNotEmpty(key) && StringUtils.isNotEmpty(value)) {
                buffer.append(URLEncoder.encode(key, Encoding.UTF8)).append("=").
                        append(URLEncoder.encode(value, Encoding.UTF8)).append("&");
            }
        }

        return buffer.deleteCharAt(buffer.length() - 1).toString();
    }

}
